<template>
  <div class="nav-app-warp" :style="{backgroundImage:'url('+curImage+')'}">
    <div class="nav-app-container">
      <div class="nav-search-warp">
        <div class="search-engine-logo">
          <img src="https://www.baidu.com/favicon.ico" alt="">
        </div>
        <input v-model="keyword" type="text" class="search-input" placeholder="搜索" @keypress.enter="search(keyword)">
        <div class="search-btn">
          <span class="iconfont icon-search" @click="search(keyword)" />
        </div>
      </div>
      <div class="nav-panel-warp">
        <div class="nav-panel-header">
          <span class="nav-panel-title">我的导航</span>
          <div class="nav-panel-right">
            <template v-if="!isEdit">
              <span class="nav-header-btn" @click="showAdd">添加</span>
              <span v-if="navs.length>0" class="nav-header-btn" @click="isEdit=true">编辑</span>
            </template>
            <span v-else class="nav-header-btn" @click="complete">完成</span>
          </div>
        </div>
        <draggable class="nav-list" :list="navs" tag="ul" v-bind="options">
          <li v-for="(item,i) in navs" :key="i" :class="{'is-move':isEdit}">
            <a :href="item.link" class="nav-link-warp" target="_blank" :title="item.name">
              <div class="nav-link-icon">
                <img :src="getIcon(item)" alt="" @error="imageError($event,item.name)">
              </div>
              <div class="nav-link-text">{{ item.name }}</div>
            </a>
            <template v-if="isEdit">
              <div class="nav-edit-mask" />
              <span class="iconfont icon-edit nav-edit-icon" @click="showEdit(item)" />
            </template>
          </li>
          <li v-if="navs.length===0">
            <div class="nav-link-warp" @click="showAdd">
              <div class="nav-link-icon">
                <img :src="getAvatar('+添加导航')" alt="">
              </div>
              <div class="nav-link-text">添加导航</div>
            </div>
          </li>
        </draggable>
      </div>
    </div>
    <Dialog v-model="isShow" :title="editForm.id?'修改链接':'添加链接'">
      <div class="ui-form-warp ui-add-from">
        <div class="ui-form-group">
          <div class="ui-form-element">
            <UiInput ref="name" v-model="editForm.name" placeholder="链接名称" :rules="rule.name" />
          </div>
        </div>
        <div class="ui-form-group">
          <div class="ui-form-element">
            <UiInput ref="link" v-model="editForm.link" placeholder="链接地址" :rules="rule.link" />
          </div>
        </div>
        <div class="ui-form-group">
          <div class="ui-form-element">
            <input v-model="editForm.icon" type="text" class="ui-form-input" placeholder="链接图标">
          </div>
        </div>
        <div class="ui-form-group">
          <div class="ui-form-element">
            <input v-model="editForm.desc" type="text" class="ui-form-input" placeholder="链接描述">
          </div>
          <div class="ui-form-btn-warp">
            <button v-if="editForm.id" class="ui-form-btn" @click="delNav(editForm)">删除</button>
            <div class="ui-btn-warp-right">
              <button class="ui-form-btn" @click="isShow=false">取消</button>
              <button class="ui-form-btn btn-primary" @click="validForm(editForm)">保存</button>
            </div>
          </div>
        </div>
      </div>
    </Dialog>
    <Dialog v-model="isExport" title="导出数据">
      <div class="nav-export-warp">
        <pre class="nav-export-pre scroll">{{ JSON.stringify(navs, null, 2) }}</pre>
      </div>
    </Dialog>
    <Dialog v-model="isImport" title="导出数据">
      <div class="nav-import-warp">
        <textarea v-model="json" class="nav-import-textarea scroll" placeholder="请输入合法的json字符串" />
        <div class="ui-form-btn-warp">
          <div class="ui-btn-warp-right">
            <button class="ui-form-btn" @click="isImport=false">取消</button>
            <button class="ui-form-btn btn-primary" @click="importData(json)">保存</button>
          </div>
        </div>
      </div>
    </Dialog>
    <Dialog v-model="isCalendar" title="日历">
      <UiCalendar />
    </Dialog>
    <div class="nav-menu-warp">
      <div class="nav-menu-btn" @click="toggleMenu">
        <span class="iconfont icon-cog" />
      </div>
      <div v-show="isMenu" class="nav-menu-list">
        <div class="nav-menu-item" @click="isCalendar=true">
          <span class="iconfont icon-calendar" />
          <span class="nav-menu-text">日历</span>
        </div>
        <div class="nav-menu-item" @click="isExport=true">
          <span class="iconfont icon-export" />
          <span class="nav-menu-text">导出数据</span>
        </div>
        <div class="nav-menu-item" @click="isImport=true">
          <span class="iconfont icon-import" />
          <span class="nav-menu-text">导入数据</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import draggable from 'vuedraggable'
import Message from '../../../components/Message'
import Dialog from '../../../components/Dialog'
import Confirm from '../../../components/Confirm'
import UiCalendar from '../../../components/UiCalendar'
import UiInput from '../../../components/UiInput'
export default {
  name: 'UiNavApp',
  components: {
    Dialog,
    draggable,
    UiCalendar,
    UiInput
  },
  data() {
    return {
      isEdit: false,
      navs: [],
      keyword: '',
      isShow: false,
      editForm: {
        id: '',
        name: '',
        link: '',
        icon: '',
        desc: ''
      },
      rule: {
        name: [
          {
            validator(value, rules, callback) {
              if (!value) {
                callback(new Error('请输入链接名称'))
              } else {
                callback()
              }
            }
          }
        ],
        link: [
          {
            validator(value, rules, callback) {
              if (!value) {
                callback(new Error('请输入链接地址！'))
              } else {
                callback()
              }
            }
          }
        ]
      },
      options: {
        animation: 500,
        handle: '.is-move'
      },
      isMenu: false,
      json: '',
      isExport: false,
      isImport: false,
      images: [
        {
          'url': 'https://cn.bing.com/th?id=OHR.PadarIsland_ZH-CN3753026244_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
          'startdate': '20210305',
          'copyright': '弗洛勒斯岛上的纳闽巴霍，印度尼西亚科莫多国家公园 (© Thrithot/Adobe Stock)'
        },
        {
          'url': 'https://cn.bing.com/th?id=OHR.MinasdeRioTinto_ZH-CN3632728092_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
          'startdate': '20210304',
          'copyright': '力拓河中含矿物质的水，西班牙里奥廷托矿区 (© David Santiago Garcia/Getty Images)'
        },
        {
          'url': 'https://cn.bing.com/th?id=OHR.Comma_ZH-CN3584865247_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
          'startdate': '20210303',
          'copyright': '努沙杜瓦海岸与防波堤，印度尼西亚巴厘岛 (© Dkart/Getty Images)'
        },
        {
          'url': 'https://cn.bing.com/th?id=OHR.WWDLions_ZH-CN3506997987_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
          'startdate': '20210302',
          'copyright': '纳库鲁湖周围森林中的两只母狮子，肯尼亚    (© Scott Davis/Tandem Stills + Motion)'
        },
        {
          'url': 'https://cn.bing.com/th?id=OHR.VolcanoLlaima_ZH-CN3436127573_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
          'startdate': '20210301',
          'copyright': '亚伊马火山与前景中的智利南洋杉，智利孔吉利奥国家公园 (© Fotografías Jorge León Cabello/Getty Images)'
        },
        {
          'url': 'https://cn.bing.com/th?id=OHR.BlueTitDaffs_ZH-CN3333224685_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
          'startdate': '20210228',
          'copyright': '威尔士中部水仙花中的蓝山雀 (© Philip Jones/Alamy)'
        },
        {
          'url': 'https://cn.bing.com/th?id=OHR.TurfHouse_ZH-CN3250210711_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
          'startdate': '20210227',
          'copyright': '斯卡夫塔山中的传统农舍，冰岛瓦特纳冰川国家公园 (© Jarcosa/Getty Images)'
        },
        {
          'url': 'https://cn.bing.com/th?id=OHR.SchneebergOchsenkopf_ZH-CN3115679592_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
          'startdate': '20210226',
          'copyright': '鸟瞰施内贝格山脉-奥克森峰，德国 (© Felix Meyer/Adobe Stock)'
        }
      ],
      curImage: 'https://cn.bing.com/th?id=OHR.LeMorneBrabant_ZH-CN9699020288_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp',
      valid: {
        name: false,
        link: false
      },
      isCalendar: false
    }
  },
  mounted() {
    const _this = this
    const len = _this.images.length
    const jsonStr = localStorage.getItem('links')
    let navs = []
    if (jsonStr) {
      try {
        navs = JSON.parse(jsonStr)
      } catch (e) {
        console.log(e)
      }
      this.navs = navs
    }
    setInterval(() => {
      const i = parseInt(Math.random() * len)
      const url = _this.images[i].url
      const img = new Image()
      img.addEventListener('load', () => {
        _this.curImage = url
      })
      img.src = url
    }, 30000)
  },
  methods: {
    search(keyWord) {
      window.open('https://www.baidu.com/s?wd=' + keyWord, '_blank')
    },
    getAvatar(name) {
      const temp = []
      temp.push('#')
      for (let index = 0; index < name.length; index++) {
        temp.push(parseInt(name[index].charCodeAt(0), 10).toString(16))
      }
      const color = temp.slice(0, 5).join('').slice(0, 7)
      const svg = `<svg width="62" height="62" xmlns="http://www.w3.org/2000/svg">
                  <g>
                    <rect stroke="#000" rx="8" id="svg_1" height="62" width="62" y="0" x="0" stroke-width="0" fill="${color}"/>
                    <text xml:space="preserve"  text-anchor="middle" dominant-baseline="middle" font-family="Helvetica, Arial, sans-serif" font-size="35" y="33" x="31" stroke-width="0" stroke="#000" fill="#ffffff">${name[0]}</text>
                  </g>
                </svg>`
      const txt = svg.replace('<svg', svg.indexOf('xmlns') ? '<svg' : '<svg xmlns="http://www.w3.org/2000/svg"')
        .replace(/"/g, "'").replace(/%/g, '%25')
        .replace(/#/g, '%23').replace(/{/g, '%7B')
        .replace(/}/g, '%7D').replace(/</g, '%3C')
        .replace(/>/g, '%3E').replace(/\s+/g, ' ')
      const url = 'data:image/svg+xml,' + txt
      return url
    },
    imageError(e, name) {
      e.target.src = this.getAvatar(name)
    },
    showEdit(item) {
      this.valid = {
        name: false,
        link: false
      }
      this.$refs['name'].resetField()
      this.$refs['link'].resetField()
      const nav = Object.assign({}, item)
      this.editForm = nav
      this.isShow = true
    },
    showAdd() {
      this.valid = {
        name: false,
        link: false
      }
      this.$refs['name'].resetField()
      this.$refs['link'].resetField()
      this.editForm = {
        id: '',
        name: '',
        link: '',
        icon: '',
        desc: ''
      }
      this.isShow = true
    },
    save(form) {
      const isName = this.validName()
      const isLink = this.validLink()
      if (!(isName && isLink)) {
        return
      }
      if (form.id) {
        const index = this.navs.findIndex(item => item.id === form.id)
        if (index !== -1) {
          this.navs[index] = { ...form }
          Message.success('链接信息修改成功！')
        }
      } else {
        form.id = new Date().getTime() + ''
        this.navs.push(form)
        Message.success('链接添加成功！')
        this.refreshLocal()
      }
      this.isShow = false
    },
    delNav(form) {
      Confirm('是否删除该链接，删除后不可恢复是否继续？')
        .then(() => {
          const index = this.navs.findIndex(item => item.id === form.id)
          if (index !== -1) {
            this.navs.splice(index, 1)
          }
          this.isShow = false
          Message.success('删除成功！')
        })
    },
    complete() {
      this.refreshLocal()
      this.isEdit = false
    },
    refreshLocal() {
      localStorage.setItem('links', JSON.stringify(this.navs))
    },
    getIcon(nav) {
      if (nav.icon) {
        return nav.icon
      } else {
        return this.getAvatar(nav.name)
      }
    },
    toggleMenu() {
      const _this = this
      function hide() {
        document.removeEventListener('click', hide)
        _this.isMenu = false
      }
      if (this.isMenu) {
        hide()
      } else {
        this.isMenu = true
        setTimeout(() => {
          document.addEventListener('click', hide)
        }, 0)
      }
    },
    importData(json) {
      if (!json) {
        Message.warning('请输入合法的json字符串！')
        return
      }
      this.navs = JSON.parse(json)
      this.refreshLocal()
      this.isImport = false
      Message.success('导入成功！')
    },
    validName() {
      if (!this.editForm.name) {
        this.valid.name = true
        return false
      } else {
        this.valid.name = false
        return true
      }
    },
    validLink() {
      if (!this.editForm.link) {
        this.valid.link = true
        return false
      } else {
        this.valid.link = false
        return true
      }
    },
    validForm(from) {
      Promise.all([this.$refs['name'].validate(), this.$refs['link'].validate()])
        .then(() => {
          this.save(from)
        })
    }
  }
}
</script>

<style scoped lang="less">
  .nav-app-warp{
    width: 100%;
    height: 100%;
    overflow-y: auto;
    position: relative;
    background-image: url("https://cn.bing.com/th?id=OHR.LeMorneBrabant_ZH-CN9699020288_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp");
    background-repeat: no-repeat;
    background-position: center;
    background-size: cover;
  }
  .nav-app-container{
    padding-top: 100px;
    width: 1000px;
    margin: 0 auto;
  }
  .nav-search-warp{
    width: 100%;
    position: relative;
  }
  .search-input{
    width: 100%;
    padding: 15px 40px 15px 50px;
    height: 50px;
    border-radius: 25px;
    outline: none;
    border: none;
    background-color: #ffffff;
    font-size: 14px;
    color: #333333;
    line-height: 20px;
    box-sizing: border-box;
  }
  .search-engine-logo{
    position: absolute;
    width: 20px;
    height: 20px;
    padding: 15px;
    left: 0;
    top: 0;
    box-sizing: content-box;
  }
  .search-engine-logo img{
    display: block;
    width: 20px;
    height: 20px;
    border-radius: 4px;
    border: none;
  }
  .search-btn{
    position: absolute;
    height: 50px;
    width: 30px;
    right: 10px;
    top: 0;
    line-height: 50px;
    text-align: center;
    cursor: pointer;
  }
  .search-btn span.iconfont{
    font-size: 20px;
    color: #666666;
  }
  .nav-panel-warp{
    background-color: rgba(255, 255, 255, 0.9);
    border-radius: 4px;
    padding: 10px 0;
    margin-top: 40px;
  }
  .nav-panel-header{
    height: 30px;
    line-height: 30px;
    padding: 0 15px;
  }
  .nav-panel-title{
    font-size: 14px;
    color: #333333;
  }
  .nav-panel-header:hover .nav-panel-right{
    display: block;
  }
  .nav-panel-right{
    float: right;
    display: none;
    height: 30px;
  }
  .nav-header-btn{
    font-size: 14px;
    display: inline-block;
    height: 30px;
    margin: 0 5px;
    color: #66b1ff;
    cursor: pointer;
  }
  .nav-list:after,.nav-link-warp:after{
    display: block;
    content: '';
    clear: both;
  }
  .nav-list{
    list-style: none;
    padding: 0 8px;
    margin: 0;
  }
  .nav-list li{
    float: left;
    box-sizing: border-box;
    position: relative;
    border-radius: 4px;
    overflow: hidden;
    width: calc(100%/6 - 16px);
    margin: 3px 8px;
  }
  .nav-link-warp{
    display: block;
    text-decoration: none;
    padding: 10px 7px 10px 7px;
    border-radius: 4px;
    cursor: pointer;
  }
  .nav-link-warp:hover{
    background-color: #f7f7f7;
  }
  .nav-link-warp:hover .nav-link-text{
    color: #66b1ff;
  }
  .nav-link-icon{
    display: block;
    float: left;
    width: 20px;
    height: 20px;
  }
  .nav-link-icon img{
    display: block;
    width: 100%;
    height: 100%;
  }
  .nav-link-text{
    margin-left: 25px;
    line-height: 20px;
    font-size: 14px;
    color: #333333;
    height: 20px;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
  }
  .nav-edit-mask{
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    border-radius: 4px;
    cursor: move;
  }
  .nav-edit-icon{
    position: absolute;
    width: 20px;
    height: 20px;
    cursor: pointer;
    right: 0;
    padding: 10px 5px;
    top: 0;
    border-radius: 0 4px 4px 0;
    font-size: 18px;
    color: #666666;
    line-height: 20px;
  }
  .is-move .nav-link-text{
    margin-right: 20px;
  }
  .is-move:hover .nav-edit-icon{
    color: #66b1ff;
  }
  .is-move:hover .nav-edit-mask{
    border: 1px dotted #66b1ff;
    background-color: hsla(0,0%,100%,.51);
  }
  .ui-add-from{
    width: 320px;
    padding: 15px;
  }
  .ui-add-from .ui-form-group:last-child{
    margin-bottom: 0;
  }
  .ui-form-group{
    margin-bottom: 20px;
    position: relative;
  }
  .ui-form-label{
    height: 30px;
    font-size: 14px;
    line-height: 30px;
    color: #666666;
  }
  .ui-form-input{
    font-size: 14px;
    height: 36px;
    padding: 8px 10px;
    line-height: 20px;
    box-sizing: border-box;
    color: #666666;
    outline: none;
    border: 1px solid #d1d1d1;
    border-radius: 4px;
  }
  .ui-form-input:focus{
    border: 1px solid #66b1ff;
  }
  .ui-form-element .ui-form-input{
    width: 100%;
  }
  .ui-element-error .ui-form-input{
    border: 1px solid #e64b15;
  }
  .element-error-warp{
    font-size: 12px;
    color: #e64b15;
    line-height: 20px;
    position: absolute;
    width: 100%;
    left: 0;
    top: 100%;
    padding: 0 5px;
  }
  .ui-form-btn-warp{
    height: 32px;
    margin-top: 15px;
    margin-bottom: 10px;
  }
  .ui-form-btn{
    display: inline-block;
    font-size: 14px;
    color: #3a8ee6;
    border: 1px solid #dadce0;
    line-height: 30px;
    padding: 0 16px;
    border-radius: 4px;
    text-decoration: none;
    outline: none;
    background-color: transparent;
    cursor: pointer;
  }
  .ui-form-btn.btn-primary{
    color: #ffffff;
    border: 1px solid #3a8ee6;
    background-color: #3a8ee6;
  }
  .ui-btn-warp-right{
    float: right;
    height: 32px;
  }
  .ui-btn-warp-right .btn-primary{
    margin-left: 10px;
  }
  .is-move.sortable-ghost{
    opacity: 0;
  }
  .nav-menu-warp{
    width: 30px;
    height: 30px;
    position: fixed;
    right: 40px;
    bottom: 20px;
  }
  .nav-menu-btn{
    display: block;
    width: 100%;
    height: 100%;
    border-radius: 4px;
    line-height: 30px;
    text-align: center;
    cursor: pointer;
  }
  .nav-menu-btn:hover{
    background-color: rgba(51, 51, 51, 0.6);
  }
  .nav-menu-btn span.iconfont{
    font-size: 18px;
    color: #ffffff;
  }
  .nav-menu-list{
    position: absolute;
    right: 0;
    bottom: 100%;
    background-color: #ffffff;
    border-radius: 4px;
    width: 140px;
    padding: 10px 0;
    margin-bottom: 5px;
  }
  .nav-menu-item{
    padding: 0 10px;
    line-height: 30px;
    font-size: 14px;
    color: #666666;
    cursor: pointer;
  }
  .nav-menu-item span.iconfont{
    margin-right: 5px;
  }
  .nav-menu-item:hover{
    background-color: #f2f2f2;
  }
  .nav-export-warp,.nav-import-warp{
    padding: 15px;
    width: 610px;
    height: 450px;
  }
  .nav-import-textarea{
    height: 400px;
    box-sizing: border-box;
    padding: 10px;
    outline: none;
    border: 1px solid #d1d1d1;
    border-radius: 4px;
    background-color: #f9f9f9;
    line-height: 20px;
    font-size: 12px;
    color: #666666;
    width: 100%;
    resize: none;
  }
  .nav-export-pre{
    padding: 10px;
    margin: 0;
    width: 100%;
    height: 100%;
    line-height: 20px;
    font-size: 12px;
    color: #666666;
    overflow: auto;
    border: 1px solid #d1d1d1;
    border-radius: 4px;
    background-color: #f2f2f2;
    box-sizing: border-box;
  }
  /*定义滚动条宽高及背景，宽高分别对应横竖滚动条的尺寸*/
  .scroll::-webkit-scrollbar{
    width: 5px;
    height: 5px;
    background-color: rgba(255, 255, 255, 0.13);
  }
  /*定义滚动条的轨道，内阴影及圆角*/
  .scroll::-webkit-scrollbar-track{
    -webkit-box-shadow: inset 0 0 6px rgba(240, 240, 240, 0);
    border-radius: 10px;
    background-color: rgba(0, 89, 255, 0);
  }
  /*定义滑块，内阴影及圆角*/
  .scroll::-webkit-scrollbar-thumb{
    /*width: 10px;*/
    height: 20px;
    border-radius: 10px;
    -webkit-box-shadow: inset 0 0 6px rgba(236, 236, 236, 0.3);
    background-color: rgba(40, 40, 40, 0.51);
    transition: all 0.5s;
  }
</style>
